package com.weme.live.ext

import android.graphics.Outline
import android.graphics.Rect
import android.util.Log
import android.view.SurfaceView
import android.view.TextureView
import android.view.View
import android.view.ViewOutlineProvider
import androidx.media3.common.Player
import com.weme.common.AppConfig
import com.weme.common.BaseApplication
import com.weme.common.util.*
import com.weme.live.activity.LiveRoomActivity
import com.weme.common.view.PlayVideoView
import io.agora.chat.BuildConfig
import io.agora.rtc2.*
import io.agora.rtc2.Constants.*
import io.agora.rtc2.video.VideoCanvas
import io.agora.rtc2.video.VideoEncoderConfiguration


var mRtcEngine: RtcEngine? = null

//虚拟主播会用到  放在单例写了 @RtcEngineSingleton
val LiveRoomActivity.mRtcEventHandler: IRtcEngineEventHandler
    get() = object : IRtcEngineEventHandler() {
        // 监听频道内的远端用户，获取用户的 uid 信息
        override fun onUserJoined(uid: Int, elapsed: Int) {
            Log.e("LiveRoom", "onUserJoined = " + uid)
            runOnUiThread { // 获取 uid 后，设置远端视频视图
                setupRemoteVideo(uid)
            }
        }

        override fun onFirstRemoteVideoFrame(uid: Int, width: Int, height: Int, elapsed: Int) {
            super.onFirstRemoteVideoFrame(uid, width, height, elapsed) //渲染器已接收首帧远端视频回调。
            //收到远端首针回调 掉一下接口 告诉服务端
            getViewModel().setFirstFrame()
            getViewModel().startTimer()


        }

        override fun onError(err: Int) {
            super.onError(err)
            Log.e("LiveRoom", "onError = " + err)
            if (BuildConfig.DEBUG) {
                when (err) {
                    ERR_FAILED -> {
                        showToast("错误码 $err：rtc 一般性的错误（没有明确归类的错误原因）。请重新调用方法。")
                    }
                    ERR_INVALID_ARGUMENT -> {
                        showToast("错误码 $err：方法中设置了无效的参数。例如指定的频道名中含有非法字符。请重新设置参数。")
                    }
                    ERR_NOT_READY -> {
                        showToast("错误码 $err：SDK 尚未准备好。可能的原因有：\n" + "RtcEngine 初始化失败。请重新初始化 RtcEngine。\n" + "调用方法时用户尚未加入频道。请检查方法的调用逻辑。\n" + "调用 rate 或 complain 方法时用户尚未离开频道。请检查方法的调用逻辑。\n" + "请检查是否已开启音频模块。请检查程序集完整性。")
                    }
                    ERR_NOT_SUPPORTED -> {
                        showToast("错误码 $err：RtcEngine 当前状态不支持该操作。可能的原因有：\n" + "Android 平台调用 setBeautyEffectOptions 方法时，如果设备版本低于 Android 5.0，会上报该错误码。请确认 Android 设备版本。\n" + "使用内置加密时，设置的加密模式不正确，或加载外部加密库失败。请检查加密的枚举值是否正确，或重新加载外部加密库。")
                    }
                    ERR_REFUSED -> {
                        showToast("错误码 $err：方法调用被拒绝。可能的原因有：\n" + "RtcEngine 初始化失败。请重新初始化 RtcEngine。\n" + "在加入频道时，将频道名设为空字符 \"\"。请重新设置频道名。\n" + "多频道场景下，在调用 joinChannelEx 方法加入频道时，设置的频道名已存在。请重新设置频道名。")
                    }
                    ERR_BUFFER_TOO_SMALL -> {
                        showToast("错误码 $err：缓冲区大小不足以存放返回的数据。")
                    }
                    ERR_NOT_INITIALIZED -> {
                        showToast("错误码 $err：RtcEngine 尚未初始化就调用方法。请确认在调用该方法前已创建 RtcEngine 对象并完成初始化。")
                    }
                    ERR_INVALID_STATE -> {
                        showToast("错误码 $err：当前状态无效。")
                    }
                    ERR_NO_PERMISSION -> {
                        showToast("错误码 $err：没有操作权限。请检查用户是否授予了 app 音视频设备的使用权限。")
                    }
                    ERR_TIMEDOUT -> {
                        showToast("错误码 $err：方法调用超时。有些方法调用需要 SDK 返回结果，如果 SDK 处理事件过长，超过 10 秒没有返回，会出现此错误。")
                    }
                    ERR_JOIN_CHANNEL_REJECTED -> {
                        showToast("错误码 $err：加入频道被拒绝。可能的原因有：\n" + "用户已经在频道中。建议通过 onConnectionStateChanged 回调判断用户是否在频道中。除收到 CONNECTION_STATE_DISCONNECTED(1) 状态外，不要再次调用该方法加入频道。\n" + "用户在调用 startEchoTest [3/3] 进行通话测试后，未调用 stopEchoTest 结束当前测试就尝试加入频道。开始通话测试后，需要先调用 stopEchoTest 结束当前测试，再加入频道。")
                    }
                    ERR_LEAVE_CHANNEL_REJECTED -> {
                        showToast("错误码 $err：离开频道失败。可能的原因有：\n" + "调用 leaveChannel [2/2] 前，用户已离开频道。停止调用该方法即可。\n" + "用户尚未加入频道，就调用 leaveChannel [2/2] 退出频道。这种情况下无需额外操作。")
                    }
                    ERR_ALREADY_IN_USE -> {
                        showToast("错误码 $err：资源已被占用，不能重复使用。")
                    }
                    ERR_ABORTED -> {
                        showToast("错误码 $err：SDK 放弃请求，可能由于请求的次数太多。")
                    }
                    ERR_RESOURCE_LIMITED -> {
                        showToast("错误码 $err：SDK 分配资源失败，可能由于 app 占用资源过多或系统资源耗尽。")
                    }
                    ERR_INVALID_APP_ID -> {
                        showToast("错误码 $err：不是有效的 App ID。请更换有效的 App ID 重新加入频道。")
                    }
                    ERR_INVALID_CHANNEL_NAME -> {
                        showToast("错误码 $err：不是有效的频道名。可能的原因是设置的参数数据类型不正确。请更换有效的频道名重新加入频道。")
                    }
                    ERR_NO_SERVER_RESOURCES -> {
                        showToast("错误码 $err：无法获取当前区域的服务器资源。请在初始化 RtcEngine 时尝试指定其他区域。")
                    }
                    ERR_TOKEN_EXPIRED -> {
                        showToast("错误码 $err：当前使用的 Token 过期，不再有效。请在服务端申请生成新的 Token，并调用 renewToken 更新 Token。")
                    }
                    ERR_INVALID_TOKEN -> {
                        showToast("错误码 $err：Token 无效。可能的原因：\n" + "在控制台中启用了 App 证书，但未使用 App ID + Token 鉴权。当项目启用了 App 证书，就必须使用 Token 鉴权。\n" + "生成 Token 时填入的 uid 字段，和用户加入频道时填入的 uid 不匹配。")
                    }
                    ERR_CONNECTION_INTERRUPTED -> {
                        showToast("错误码 $err：网络连接中断。SDK 在和服务器建立连接后，失去网络连接超过 4 秒。")
                    }
                    ERR_CONNECTION_LOST -> {
                        showToast("错误码 $err：网络连接丢失。网络连接中断，且 SDK 无法在 10 秒内连接服务器。")
                    }
                    ERR_NOT_IN_CHANNEL -> {
                        showToast("错误码 $err：调用 sendStreamMessage 方法时用户不在频道内。")
                    }
                    ERR_SIZE_TOO_LARGE -> {
                        showToast("错误码 $err：在调用 sendStreamMessage 时，发送的数据长度大于 1 KB。")
                    }
                    ERR_BITRATE_LIMIT -> {
                        showToast("错误码 $err：在调用 sendStreamMessage 时，发送数据的频率超过限制（6 KB/s）。")
                    }
                    ERR_TOO_MANY_DATA_STREAMS -> {
                        showToast("错误码 $err：在调用 createDataStream [2/2] 时，创建的数据流超过限制（5 个）。")
                    }
                    ERR_STREAM_MESSAGE_TIMEOUT -> {
                        showToast("错误码 $err：数据流发送超时。")
                    }
                    ERR_SET_CLIENT_ROLE_NOT_AUTHORIZED -> {
                        showToast("错误码 $err：用户切换角色失败，请尝试重新加入频道。")
                    }
                    ERR_DECRYPTION_FAILED -> {
                        showToast("错误码 $err：解密失败。可能是用户加入频道时使用了错误的密码。请检查用户加入频道时填入的密码，或引导用户尝试重新加入频道。")
                    }
                    ERR_INVALID_USER_ID -> {
                        showToast("错误码 $err：该用户 ID 无效。")
                    }
                    ERR_CLIENT_IS_BANNED_BY_SERVER -> {
                        showToast("错误码 $err：该用户被服务器禁止。")
                    }
                    ERR_ENCRYPTED_STREAM_NOT_ALLOWED_PUBLISH -> {
                        showToast("错误码 $err：SDK 不支持将加密过的流推到 CDN 上。")
                    }
                    ERR_INVALID_USER_ACCOUNT -> {
                        showToast("错误码 $err：无效的 user account，可能是因为设置了无效的参数。")
                    }
                    ERR_LOAD_MEDIA_ENGINE -> {
                        showToast("错误码 $err：加载媒体引擎失败。")
                    }
                    ERR_ADM_GENERAL_ERROR -> {
                        showToast("错误码 $err：音频设备出现错误（未指明何种错误）。请检查音频设备是否被其他应用占用，或者尝试重新进入频道。")
                    }
                    ERR_ADM_INIT_PLAYOUT -> {
                        showToast("错误码 $err：初始化播放设备出错。请检查播放设备是否被其他应用占用，或者尝试重新进入频道。")
                    }
                    ERR_ADM_START_PLAYOUT -> {
                        showToast("错误码 $err：启动播放设备出错。请检查播放设备是否正常。")
                    }
                    ERR_ADM_STOP_PLAYOUT -> {
                        showToast("错误码 $err：停止播放设备出错。")
                    }
                    ERR_ADM_INIT_RECORDING -> {
                        showToast("错误码 $err：初始化录音设备出错。请检查录音设备是否正常，或者尝试重新进入频道。")
                    }
                    ERR_ADM_START_RECORDING -> {
                        showToast("错误码 $err：启动录音设备出错。请检查录音设备是否正常。")
                    }
                    ERR_ADM_STOP_RECORDING -> {
                        showToast("错误码 $err：停止录音设备出错。")
                    }
                    ERR_VDM_CAMERA_NOT_AUTHORIZED -> {
                        showToast("错误码 $err：没有摄像头使用权限。请检查是否已经打开摄像头权限。")
                    }
                }
            }

        }

        //加入频道成功
        override fun onJoinChannelSuccess(channel: String?, uid: Int, elapsed: Int) {
            super.onJoinChannelSuccess(channel, uid, elapsed)
            Log.e("LiveRoom", "onJoinChannelSuccess = " + channel)
        }

        override fun onUserInfoUpdated(uid: Int, userInfo: UserInfo?) {
            super.onUserInfoUpdated(uid, userInfo)
            Log.e("LiveRoom", "onUserInfoUpdated = " + uid) //远端用户信息已更新回调。
        }

        override fun onConnectionStateChanged(state: Int, reason: Int) {
            super.onConnectionStateChanged(state, reason)
            if (BuildConfig.DEBUG) {
                when (reason) {
                    CONNECTION_CHANGED_CONNECTING -> {
                        showToast("rtc 建立网络连接中")
                    }
                    CONNECTION_CHANGED_JOIN_SUCCESS -> {
                        showToast("rtc 成功加入频道")
                    }
                    CONNECTION_CHANGED_INTERRUPTED -> {
                        showToast("rtc  网络连接中断")
                    }
                    CONNECTION_CHANGED_BANNED_BY_SERVER -> {
                        showToast("rtc 网络连接被服务器禁止")
                    }
                    CONNECTION_CHANGED_JOIN_FAILED -> {
                        showToast("rtc 加入频道失败")
                    }
                    CONNECTION_CHANGED_LEAVE_CHANNEL -> {
                        showToast("rtc 离开频道")
                    }
                    CONNECTION_CHANGED_INVALID_APP_ID -> {
                        showToast("rtc 不是有效的 APP ID。请更换有效的 APP ID 重新加入频道")
                    }
                    CONNECTION_CHANGED_INVALID_CHANNEL_NAME -> {
                        showToast("rtc 不是有效的频道名。请更换有效的频道名重新加入频道")
                    }
                    CONNECTION_CHANGED_INVALID_TOKEN -> {
                        showToast("rtc 生成的 Token 无效。一般有以下原因：\n" + "在控制台上启用了 App Certificate，但加入频道未使用 Token。当启用了 App Certificate，必须使用 Token。\n" + "在调用 joinChannel [2/2] 加入频道时指定的 uid 与生成 Token 时传入的 uid 不一致。")
                    }
                    CONNECTION_CHANGED_TOKEN_EXPIRED -> {
                        showToast("rtc 当前使用的 Token 过期，不再有效，需要重新在你的服务端申请生成 Token")
                    }
                    CONNECTION_CHANGED_REJECTED_BY_SERVER -> {
                        showToast("rtc 此用户被服务器禁止")
                    }
                    CONNECTION_CHANGED_SETTING_PROXY_SERVER -> {
                        showToast("rtc 由于设置了代理服务器，SDK 尝试重连")
                    }
                    CONNECTION_CHANGED_RENEW_TOKEN -> {
                        showToast("rtc 更新 Token 引起网络连接状态改变")
                    }
                    CONNECTION_CHANGED_CLIENT_IP_ADDRESS_CHANGED -> {
                        showToast("rtc 客户端 IP 地址变更，可能是由于网络类型，或网络运营商的 IP 或端口发生改变引起")
                    }
                    CONNECTION_CHANGED_KEEP_ALIVE_TIMEOUT -> {
                        showToast("rtc SDK 和服务器连接保活超时，进入自动重连状态")
                    }
                    CONNECTION_CHANGED_REJOIN_SUCCESS -> {
                        showToast("rtc 重新加入频道成功")
                    }
                    CONNECTION_CHANGED_LOST -> {
                        showToast("rtc SDK 和服务器失去连接")
                    }
                    CONNECTION_CHANGED_ECHO_TEST -> {
                        showToast("rtc 连接状态变化由回声测试引起")
                    }
                    CONNECTION_CHANGED_CLIENT_IP_ADDRESS_CHANGED_BY_USER -> {
                        showToast("rtc 本地 IP 地址被用户更改")
                    }
                    CONNECTION_CHANGED_SAME_UID_LOGIN -> {
                        showToast("rtc 使用相同的 UID 从不同的设备加入同一频道")
                    }
                    CONNECTION_CHANGED_TOO_MANY_BROADCASTERS -> {
                        showToast("rtc 频道内主播人数已达上限")
                    }
                    else -> {
                        showToast("rtc 未知错误")
                    }
                }
            }

            Log.e("LiveRoom", "onConnectoionStateChanged->, state->$state, reason->$reason")
        }

    }


fun LiveRoomActivity.setupRemoteVideo(uid: Int) {
    getViewBinding().localVideoViewContainer.post {
         surfaceView = SurfaceView(baseContext)
        surfaceView?.setZOrderMediaOverlay(false)
        getViewBinding().localVideoViewContainer.addView(surfaceView) // 将 SurfaceView 对象传入声网实时互动 SDK，设置远端视图
        mRtcEngine?.setupRemoteVideo(VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_HIDDEN, uid))
    }

}


//先创建rtc 在加入房间
fun LiveRoomActivity.initConifg() {
//    mRtcEngine = RtcEngineSingleton.getRtcEngine()
//    RtcEngineSingleton.setRtcEngineListener(object : RtcEngineListener {
//        override fun onUserJoined(uid: Int) {
//            runOnUiThread { // 获取 uid 后，设置远端视频视图
//                setupRemoteVideo(uid)
//            }
//        }
//
//        override fun onFirstRemoteVideoFrame() {
//            getViewModel().setFirstFrame()
//            getViewModel().startTimer()
//        }
//
//    })
    val config = RtcEngineConfig()
        config.mContext = BaseApplication.sInstance
        config.mAppId = AppConfig.APP_ID
        config.mEventHandler = mRtcEventHandler
        config.mAudioScenario = AudioScenario.getValue(AudioScenario.CHATROOM) // 创建并初始化 RtcEngine
        mRtcEngine = RtcEngine.create(config)
        // 调用 setAudioProfile，将场景设置为 AUDIO_PROFILE_MUSIC_HIGH_QUALITY 或 AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO
        //设置音频编码属性和音频场景  AUDIO_PROFILE_SPEECH_STANDARD = 标准语音场景配置。适用于通话、语音聊天等语音通信场景。
        mRtcEngine?.setAudioProfile(AUDIO_PROFILE_SPEECH_STANDARD)


}

fun LiveRoomActivity.initVideo(token: String, channelId: String) { //启用视频模块。
    mRtcEngine?.enableVideo()
    mRtcEngine?.startPreview() //开启视频预览。
    getViewBinding().remoteVideoViewContainer.post {
        val surfaceView = TextureView(baseContext)
        getViewBinding().remoteVideoViewContainer.addView(surfaceView)
       // surfaceView.gone()
        mRtcEngine?.setupLocalVideo(VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_HIDDEN, 0))
        //surfaceView.fadeOut()
    }

    //初始化本地视频

    val options = ChannelMediaOptions().apply { //用户角色
        clientRoleType = CLIENT_ROLE_BROADCASTER //主播端
        audienceLatencyLevel = AUDIENCE_LATENCY_LEVEL_ULTRA_LOW_LATENCY //超低延迟
        channelProfile = CHANNEL_PROFILE_COMMUNICATION_1v1
    }
    val uid = UserMKHelper.decodeLong(UserMKHelper.UID).toInt()
    mRtcEngine?.joinChannel(token, channelId, uid, options)
    mRtcEngine?.setVideoEncoderConfiguration(VideoEncoderConfiguration())


    println("LiveRoomActivity Config -> token = ${token}, channel = ${channelId} uid = ${uid}")
}

fun LiveRoomActivity.oneselfCamera() {
    val config = RtcEngineConfig()
    config.mContext = baseContext
    config.mAppId = AppConfig.APP_ID
    config.mEventHandler = mRtcEventHandler
    config.mAudioScenario = AudioScenario.getValue(AudioScenario.CHATROOM) // 创建并初始化 RtcEngine
    mRtcEngine = RtcEngine.create(config) // 调用 setAudioProfile，将场景设置为 AUDIO_PROFILE_MUSIC_HIGH_QUALITY 或 AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO
    mRtcEngine?.setAudioProfile(AUDIO_PROFILE_DEFAULT)
    mRtcEngine?.enableVideo()
    mRtcEngine?.startPreview()
    val surfaceView = TextureView(baseContext)
    surfaceView.outlineProvider = object : ViewOutlineProvider() {
        override fun getOutline(view: View?, outline: Outline?) {
            val rect = Rect()
            view!!.getGlobalVisibleRect(rect)
            val leftMargin = 0
            val topMargin = 0
            val selfRect = Rect(leftMargin, topMargin, rect.right - rect.left - leftMargin, rect.bottom - rect.top - topMargin)
            outline!!.setRoundRect(selfRect, 30f)
        }
    }

    surfaceView.clipToOutline = true // surfaceView.holder.setFormat(PixelFormat.TRANSLUCENT)
    getViewBinding().remoteVideoViewContainer.addView(surfaceView)
    mRtcEngine?.setVideoEncoderConfiguration(VideoEncoderConfiguration())
    mRtcEngine?.setupLocalVideo(VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_HIDDEN, 0))
}

var playVideo: PlayVideoView? = null
fun LiveRoomActivity.playVideo(url: String) {
    playVideo = PlayVideoView(this)
    getViewBinding().localVideoViewContainer.addView(playVideo)
    playVideo?.setPlayUrl(url, object : Player.Listener {
        override fun onRenderedFirstFrame() { //第一针回调
            super.onRenderedFirstFrame()
            getViewModel().startTimer()
        }
    })

}

fun LiveRoomActivity.stopPlay() {
    playVideo?.stopPlay()
}

fun LiveRoomActivity.rtcEngineDestroy() {
    mRtcEngine?.stopPreview()
    mRtcEngine?.leaveChannel()
    RtcEngine.destroy()
    getViewBinding().localVideoViewContainer.removeView(surfaceView)
}



